package com.data.center.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.data.center.dictionary.CountryCode;
import com.data.center.dictionary.OrganizationCategory;
import com.data.center.dictionary.OrganizationStatus;
import com.data.center.dto.OrganizationDto;
import com.data.center.entity.AdminDivision;
import com.data.center.entity.Organization;
import com.data.center.entity.foreignDemo.Children1;
import com.data.center.exception.exception.BizException;
import com.data.center.exception.info.CommonEnum;
import com.data.center.mapper.OrganizationMapper;
import com.data.center.service.AdminDivisionService;
import com.data.center.service.OrganizationService;
import com.data.center.util.AdminDivisionUtils;
import com.data.center.util.CalculateUtils;
import com.data.center.util.ForeignManage.ForeignDataItem;
import com.data.center.util.ForeignManage.ForeignManageUtils;
import com.data.center.util.SnowflakeIdWorker;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jodd.util.StringUtil;

@Service
@Transactional
@Slf4j
public class OrganizationServiceImpl implements OrganizationService {

    @Autowired
    private OrganizationMapper organizationMapper;
    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;
    @Autowired
    ForeignManageUtils foreignManageUtils;
    @Autowired
    ApplicationContext applicationContext;

    @Autowired
    AdminDivisionService adminDivisionService;

    private static final String DELETE = "DELETE";
    private static final String COVER_MODE = "COVER_MODE";


    public static List<KeyVerifyStandardizeTableItem> keyVerifyStandardizeTable = new ArrayList<>();


    public void initKeyVerifyStandardizeTableItem() throws NoSuchMethodException {
        if (keyVerifyStandardizeTable.size() > 0) {
            return;
        }
        // 初始化键-校验-标准化对应表
        keyVerifyStandardizeTable.add(
                new KeyVerifyStandardizeTableItem(
                        "name",
                        OrganizationServiceImpl.class.getMethod("nameVerify", String.class),
                        OrganizationServiceImpl.class.getMethod("nameStandardize",  String.class))
        );
        keyVerifyStandardizeTable.add(
                new KeyVerifyStandardizeTableItem(
                        "abbreviation",
                        OrganizationServiceImpl.class.getMethod("abbreviationVerify", List.class),
                        OrganizationServiceImpl.class.getMethod("abbreviationStandardize", List.class))
        );
        keyVerifyStandardizeTable.add(
                new KeyVerifyStandardizeTableItem(
                        "category",
                        OrganizationServiceImpl.class.getMethod("categoryVerify", String.class),
                        OrganizationServiceImpl.class.getMethod("categoryStandardize", String.class))
        );
        keyVerifyStandardizeTable.add(
                new KeyVerifyStandardizeTableItem(
                        "country",
                        OrganizationServiceImpl.class.getMethod("countryVerify", String.class),
                        OrganizationServiceImpl.class.getMethod("countryStandardize", String.class))
        );
        keyVerifyStandardizeTable.add(
                new KeyVerifyStandardizeTableItem(
                        "divisionCode",
                        OrganizationServiceImpl.class.getMethod("divisionCodeVerify", String.class),
                        OrganizationServiceImpl.class.getMethod("divisionCodeStandardize", String.class))
        );
    }

    /**
     * @Description:行政区划代码的正确性（O-P1）：工作单位的行政区划代码无误。
    */
//    public boolean checkDivisionCode(String code) {
//
//        // 检查长度
//        if (AdminDivisionUtils.checkCodeLengthIsSix(code)) {
//            // 对6位原始编码进行解析
//            code = AdminDivisionUtils.getDivisionFatherCode(code).substring(0, 2) + code;
//        } else if (AdminDivisionUtils.checkCodeLengthIsEight(code)) {
//            // 8位编码无需进行操作
//        } else {
//            throw new BizException(CommonEnum.DIVISION_CODE_WRONG);
//        }
//
//        // 检查编码是否在库中存在
//        AdminDivision adminDivision = adminDivisionService.getByCode(code);
//        if (adminDivision == null) {
//            throw new BizException(CommonEnum.ADMIN_DIVISION_CODE_NOT_EXIST);
//        }
//
//        return true;
//    }


    /**
     * @Description:通过输入机构名称和简称，来检索机构，可能检索到多个机构
     * */
    @Override
    public List<OrganizationDto> findOrganization(String name, String abbreviation) {
        // 统一编码，删除空格
        name = nameStandardize(name);
        // 由于反序列化是使用typeHandler在查询后自动实现的，故查询条件拼接在mapper里实现，使得service层统一，无需自行处理名称后的逗号
        abbreviation = nameStandardize(abbreviation);

        // 只要不全为空均可进行查询
        if (StrUtil.isNotEmpty(name) || StrUtil.isNotEmpty(abbreviation)) {
            return organizationMapper.findOrganization(name, abbreviation);
        }

        return null;
    }


    /**
     * @Description:通过输入机构名称和多个简称，来检索机构，可能检索到多个机构
     * */
//    @Override
    public List<OrganizationDto> findOrganizationWithAbbreviations(String name, List<String> abbreviations) {
        HashSet<OrganizationDto> findResult = new HashSet<>();

        if (StrUtil.isNotEmpty(name)) {
            findOrganization(name, null).forEach(item -> findResult.add(item));
        }

        if (abbreviations != null && abbreviations.size() > 0) {
            abbreviations.forEach(item -> findOrganization(null, item).forEach(find -> findResult.add(find)));
        }

        List<OrganizationDto> result = new ArrayList<>(findResult);
        return result;
    }


    /**
     * @Description:尝试添加一个新机构
     * */
    @Override
    public OrganizationDto addOrganization(OrganizationDto organizationDto) {
        log.info("添加组织函数被调用");

        // 根据名称和简称核验唯一性
        List<OrganizationDto> allOld = new ArrayList<>();

        // 检查名称
        List<OrganizationDto> originalName = findOrganization(organizationDto.getName(), null);
        if (originalName != null && originalName.size() > 0) {
            allOld.addAll(originalName);
        }
        // 检查简称
        if (organizationDto.getAbbreviation() != null && organizationDto.getAbbreviation().size() > 0) {
            organizationDto.getAbbreviation().forEach(item -> {
                List<OrganizationDto> originalAbbreviation = findOrganization(null, item);
                if (originalAbbreviation != null && originalAbbreviation.size() > 0) {
                    allOld.addAll(originalAbbreviation);
                }
            });
        }
        if (allOld.size() > 0) {
            throw new BizException(CommonEnum.ORGANIZATION_EXIST);
        }

        // 各项属性verify及标准化
        OrganizationDto newOrgnization = BeanUtil.copyProperties(organizationDto, OrganizationDto.class);
        // 将所有键都添加进入增量信息列表，用于标志哪些字段需要被检查
        Arrays.stream(OrganizationDto.class.getDeclaredFields()).map(field -> newOrgnization.getAdditionalInformation().put(field.getName(), ""));
        List<String> errorList = standardizeOrganization(newOrgnization);

        // 自动生成唯一ID
        newOrgnization.setOrganizationId(String.valueOf(snowflakeIdWorker.nextId()));
        // 设置审批相关字段
        newOrgnization.setStatus(newOrgnization.getStatus() == null ? Integer.valueOf(OrganizationStatus.NOT_REVIEWED.getKey()) : newOrgnization.getStatus());

        organizationMapper.insertOrganization(newOrgnization);

        log.error("不符合入库条件的数据项有:\n" + errorList + "\n已自动处理");
        log.info("添加组织函数单词调用结束");
        return newOrgnization;
    }

    public List<String> standardizeOrganization(OrganizationDto newOrgnization) {
        List<String> errorList = new ArrayList<>(); // 不符合入库标准但可以自动格式化的数据项

        // 根据增量信息校验和标准化需要更新的字段，如果该字段有核验和标准化方法，则进行核验和标准化
        newOrgnization.getKeyWithAdditionalInformation().forEach(item -> {
            for (KeyVerifyStandardizeTableItem tableItem : this.keyVerifyStandardizeTable) {
                if (tableItem.key.equals(item)) {
                    try {
                        boolean isPass = (boolean) tableItem.verify.invoke(this, getAttributeValue(newOrgnization, item.toString()));
                        if (!isPass) {
                            // 若字段未通过核验，则将字段及信息添加到错误列表
                            errorList.add("字段" + item + "未通过核验");
                            // 将待更新字段的属性值设置为标准化的结果
                            setAttributeValue(
                                    newOrgnization,
                                    item.toString(),
                                    tableItem.standatdize.invoke(this, getAttributeValue(newOrgnization, item.toString()))
                            );
                            errorList.add("字段" + item +"已自动标准化为" + getAttributeValue(newOrgnization, item.toString()));
                        } else {
                            // 若字段通过核验，则输出日志
                            log.info("字段" + item +"通过核验");
                        }
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException(e);
                    } catch (InvocationTargetException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        });


//        // 检验名称并自动格式化，将检测过程中核验出的可自动处理异常输出至日志
//        String name = newOrgnization.getName();
//        if (!nameVerify(name)) {
//            if (StrUtil.isEmpty(name)){
//                throw new BizException(CommonEnum.NAME_WRONG);
//            }
//            errorList.add("名称name: {" + newOrgnization.getName() + "}不符合入库标准");
//            newOrgnization.setName(nameStandardize(name));
//        }
//
//        // 检验简称并自动格式化
//        List<String> abbreviation = newOrgnization.getAbbreviation();
//        if (abbreviation != null && abbreviation.size() > 0) {
//            if (!abbreviationVerify(abbreviation)) {
//                errorList.add("简称: {" + abbreviation + "}不符合入库标准");
//            }
//            List<String> newAbbreviation = abbreviationStandardize(abbreviation);
////            abbreviation.forEach(item -> {
////                if (!nameVerify(item)) {
////                    errorList.add("简称: {" + item + "}不符合入库标准");
////                    if (StrUtil.isEmpty(item)){
////                        throw new BizException(CommonEnum.ABBREVIATION_WRONG);
////                    } else {
////                        // 添加格式化后的简称
////                        newAbbreviation.add(nameStandardize(item));
////                    }
////                } else {
////                    newAbbreviation.add(item);
////                }
////            });
//            newOrgnization.setAbbreviation(newAbbreviation);
//        }
//
//        // 检验单位性质是否在字典中,如果存在则统一转为编码
//        String category = newOrgnization.getCategory();
//        if (!categoryVerify(category)) {
//            errorList.add("企业类型: {" + category + "}不符合入库标准");
//            newOrgnization.setCategory(categoryStandardize(category));
//        }
//
//        // 检查国家是否在字典中，如果存在则统一转为编码
//        String country = newOrgnization.getCountry();
//        if (!countryVerify(country)) {
//            errorList.add("国家: {" + country + "}不符合入库标准");
//            newOrgnization.setCountry(countryStandardize(country));
//        }
//
//        // 行政区划代码
//        String divisionCode = newOrgnization.getDivisionCode();
//        if (!divisionCodeVerify(divisionCode)) {
//            // 不符合8位规范、或可能不在库中存在
//            errorList.add("行政区划代码: {" + divisionCode + "}不符合入库标准");
//            newOrgnization.setDivisionCode(divisionCodeStandardize(divisionCode));
//        }

        return errorList;
    }

    /**
     * @Description:检查名称是否为空，或是否存在空格或中文标点
     * */
    public boolean nameVerify(String name) {

        // 如果为空或null直接返回错误
        if (StringUtil.isEmpty(name) || name.contains(" ")) {
            return false;
        }

        // 定义中文标点正则表达式
//        String pattern = "[，。！？：；“”‘’【】《》（）]";
        String pattern = "[\\,\\.\\!\\?\\:\\;\"\\'\\[\\]\\(\\)\\<\\>\\s]";

        // 创建 Pattern 对象
        Pattern regex = Pattern.compile(pattern);

        // 创建 Matcher 对象
        Matcher matcher = regex.matcher(name);

        if (matcher.find()) {
            // 字符串包含中文标点或空格
            return false;
        }

        return true;
    }

    /**
     * @Description:标准化名称字段
     * */
    public String nameStandardize(String name) {

        // 如果无需标准化直接返回
        if (nameVerify(name)) {
            return name;
        } else if (StrUtil.isEmpty(name)) {
            return "";
        }

        // 创建中文标点字符到英文标点字符的映射表
        String[][] punctuationMap = {
                {"\\,", "，"},
                {"\\.", "。"},
                {"\\!", "！"},
                {"\\?", "？"},
                {"\\:", "："},
                {"\\;", "；"},
                {"\"", "“"},
                {"\"", "”"},
                {"\\'", "‘"},
                {"\\'", "’"},
                {"\\[", "【"},
                {"\\]", "】"},
                {"\\<", "《"},
                {"\\>", "》"},
                {"\\(", "（"},
                {"\\)", "）"},
                {" ", ""} // 空格删除
        };

        // 使用映射表将中文标点替换为英文标点
        for (String[] mapping : punctuationMap) {
            name = name.replaceAll(mapping[0], mapping[1]);
        }

        return name;
    }

    /**
     * @Description:检查简称是否为空，或是否存在空格或中文标点
     * */
    public boolean abbreviationVerify(List<String> abbreviations) {
        boolean isPass = true;
        for (int i = 0; i < abbreviations.size(); ++i) {
            if (!nameVerify(abbreviations.get(i))) {
                isPass = false;
            }
        }
        return isPass;
    }

    /**
     * @Description:标准化每个简称字段
     * */
    public List<String> abbreviationStandardize(List<String> abbreviations) {
        List<String> newAbbreviation = new ArrayList<>();
        abbreviations.forEach(item -> {
            if (StrUtil.isEmpty(item)){
                throw new BizException(CommonEnum.ABBREVIATION_WRONG);
            } else {
                // 添加格式化后的简称
                newAbbreviation.add(nameStandardize(item));
            }
        });
       return newAbbreviation;
    }

    /**
     * @Description:单位性质的正确性（O-P2）：工作单位的单位性质无误。
     * @param code 仅仅支持输入编码
     * */
    public boolean categoryVerify(String code) {
//        OrganizationCategory organizationCategory = OrganizationCategory.getKeyByValue(codeOrName);
//        if (organizationCategory == null) {
//            organizationCategory = OrganizationCategory.getValueByKey(codeOrName);
//            if (organizationCategory == null) {
//                return false;
//            }
//        }
        try {
            OrganizationCategory.getValueByKey(code);
        } catch (BizException e) {
            return false;
        }
        return true;
    }

    /**
     * @Description:标准化单位性质字段,统一转换为编码
     * @Param:可以为编码/名称
     * */
    public String categoryStandardize(String category) {
        try {
            return OrganizationCategory.getKeyByValue(category).getKey();
        } catch (BizException e) {
            try {
                return OrganizationCategory.getValueByKey(category).getKey();
            } catch (BizException bizException) {
                throw new BizException(CommonEnum.CATEGORY_NOT_EXIST);
            }
        }
    }

    /**
     * @Description:判断国家编码是否符合入库标准
     * */
    public boolean countryVerify(String code) {
        try {
            CountryCode.getObjectByThreeCharCode(code);
        } catch (BizException e) {
            return false;
        }
        return true;
    }

    /**
     * @Description:将国家名称、三位编码、数字编码转为对应的三位编码
     * */
    public String countryStandardize(String country) {
        try {
            return CountryCode.getObjectByThreeCharCode(country).getThreeCharCode();
        } catch (BizException e) {
            try {
                return CountryCode.getObjectByNumberCode(country).getThreeCharCode();
            } catch (BizException bizException) {
                try {
                    return CountryCode.getObjectByChineseName(country).getThreeCharCode();
                } catch (BizException nameBizException) {
                    throw new BizException(CommonEnum.COUNTRY_NOT_EXIST);
                }
            }
        }
    }

    /**
     * @Description:检查区域编码是否为8位，是否在库中存在
     * */
    public boolean divisionCodeVerify(String divisionCode) {
        if (!AdminDivisionUtils.checkCodeLengthIsEight(divisionCode)) {
            return false;
        }
        return adminDivisionService.getByCode(divisionCode) != null;
    }

    /**
     * @Description:标准化区域编码，对6位编码进行父编码查询拼接成8位编码，并检查是否在库中存在
     * */
    public String divisionCodeStandardize(String divisionCode) {

        // 可能传入的是区域名称，尝试进行名称查询解码
        try {
            AdminDivision adminDivision = adminDivisionService.getByName(divisionCode);
            if (adminDivision != null) {
                divisionCode = adminDivision.getCode();
            }
        } catch (MyBatisSystemException e) {
            throw new BizException(CommonEnum.ADMIN_DIVISION_NAME_CANT_GET);
        }


        // 检查编码是否为可解析或查询的位数，并自动解析6位编码
        if (AdminDivisionUtils.checkCodeLengthIsEight(divisionCode)) {

        } else if (AdminDivisionUtils.checkCodeLengthIsSix(divisionCode)) {
            // 传入的是6位，尝试直接解码
            divisionCode = AdminDivisionUtils.getFatherCode(divisionCode).substring(0, 2) + divisionCode;
        }

        // 查询编码是否在库中存在
        if (adminDivisionService.getByCode(divisionCode) != null) {
            return divisionCode;
        } else {
            throw new BizException(CommonEnum.DIVISION_CODE_WRONG);
        }
    }

    /***
     * @description: 根据增量信息及输入组织信息，对原组织进行重命名
     * */
    @Override
    public OrganizationDto renameOrganization(OrganizationDto originalOrganization, OrganizationDto updateOrganization) {
        OrganizationDto newOrg = getNewDataByMode(originalOrganization, updateOrganization);

        if (newOrg.getName().equals(originalOrganization.getName())) {
            // 判断简称是否一致
            CalculateUtils<String> calculateUtils = new CalculateUtils<>(); // 初始化交并计算工具
            if (calculateUtils.getIntersection(originalOrganization.getAbbreviation(), updateOrganization.getAbbreviation()).size() == updateOrganization.getAbbreviation().size()) {
                return originalOrganization; // 没有变动
            }
        }

        List<OrganizationDto> findResult = findOrganizationWithAbbreviations(newOrg.getName(), newOrg.getAbbreviation());
        if (findResult.size() > 1) {
            throw new BizException(CommonEnum.ORGANIZATION_RENAME_FALSE); // 若改名后查到的组织有多个，说明违反了唯一性约束
        } else if (findResult.size() == 0) {
            throw new BizException(CommonEnum.ORGANIZATION_RENAME_FALSE); // 该种情况不允许，即改名后的组织的名称和简称在原库中均不存在
        } else {
            if (!findResult.get(0).getOrganizationId().equals(originalOrganization.getOrganizationId())) {
                throw new BizException(CommonEnum.ORGANIZATION_RENAME_FALSE); // 若改名后查到的组织和原本的组织不同，说明违反了唯一性约束
            }
            organizationMapper.updateOrganization(newOrg);
            return newOrg;
        }

    }

    // 根据增量信息中的模式信息获取最新的名称与简称
    private OrganizationDto getNewDataByMode(OrganizationDto originalOrganization, OrganizationDto updateOrganization) {
        OrganizationDto resultOrg = BeanUtil.copyProperties(originalOrganization, OrganizationDto.class);

        // 名称为覆盖式更新
        if(updateOrganization.getName() != null){
            resultOrg.setName(updateOrganization.getName());
        }

        // 简称需要根据增量信息进行判断
        if (updateOrganization.getAbbreviation() != null){
            String abbreviationsUpdateMode = updateOrganization.getAdditionalInformation("abbreviation");
            CalculateUtils<String> calculateUtils = new CalculateUtils<>(); // 初始化交并计算工具
            switch (abbreviationsUpdateMode) {
                // 优化掉了，只有覆盖式更新必须指定增量信息
//            case "ADD_MODE":
//                resultOrg.setAbbreviation(
//                        calculateUtils.getUnion(originalOrganization.getAbbreviation(), updateOrganization.getAbbreviation())
//                );
                case COVER_MODE:
                    resultOrg.setAbbreviation(updateOrganization.getAbbreviation());
                    break;
                default:
                    // 默认采用增量模式
                    resultOrg.setAbbreviation(
                            calculateUtils.getUnion(originalOrganization.getAbbreviation(), updateOrganization.getAbbreviation()) // 优化，采用集合实现
                    );
            }
        }

        return resultOrg;
    }

    /**
     * @Description:审批输入组织
     * 1. 校验组织是否已经审批过
     *
     * */
    public OrganizationDto approveOrganization(OrganizationDto organizationDto) {
        organizationDto.setStatus(Integer.valueOf(OrganizationStatus.REVIEWED.getKey()));
        organizationDto.setApprovalTime(new Date());
        organizationDto.setApprover("DEFAULT"); // TODO:完成用户鉴权机制，解析用户名
        organizationMapper.updateOrganization(organizationDto);
        return organizationDto;
    }

    /**
     * @Description:根据输入的信组织数据以及其增量信息中标识的更新模式，更新旧的组织信息
     * 1. 校验增量信息中标识的更新模式是否合法
     * 2. 根据增量信息中标识的更新模式，将增量信息中的字段值设置到原组织对象中
     * 3. 如果字段有核验和标准化方法，则进行核验和标准化
     * 4. 将原组织对象更新到数据库中
     * 5. 返回更新后的组织对象
     * 6. 更新模式包括：
     * 6.1 删除：将字段设置为默认值
     * 6.2 更新：将字段设置为增量信息中的值
     * 6.3 追加：将增量信息中的值追加到原字段
     * */
    @Override
    public OrganizationDto updateOrganization(OrganizationDto originalOrganization, OrganizationDto organizationDto) {
        // 尝试初始化验证标准化方法表
        try {
            initKeyVerifyStandardizeTableItem();
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }

        // 不允许更改名称和简称字段
        Set updateKey = organizationDto.getKeyWithAdditionalInformation();
        if (updateKey.contains("name") && !originalOrganization.getName().equals(organizationDto.getName())) {
            throw new BizException(CommonEnum.NOT_ALLOWED);
        }
        CalculateUtils<String> organizationDtoCalculateUtils = new CalculateUtils<>();
        if (updateKey.contains("abbreviation") && !organizationDtoCalculateUtils.equals(originalOrganization.getAbbreviation(), organizationDto.getAbbreviation())) {
            throw new BizException(CommonEnum.NOT_ALLOWED);
        }

        // 根据增量信息设置需要更新的字段
        // 如果该字段有核验和标准化方法，则进行核验和标准化
        log.info("自动校验标准化待更新字段结果：" + standardizeOrganization(organizationDto));
        organizationDto.getKeyWithAdditionalInformation().forEach(item -> {
            switch (organizationDto.getAdditionalInformation().get(item)) {
                case DELETE:
                    setDefaultValues(originalOrganization, item.toString());
                    break;
                default: // 默认采用更新
                    setAttributeValue(originalOrganization, item.toString(), getAttributeValue(organizationDto, item.toString()));
                    break;
            }
        });
        organizationMapper.updateOrganization(originalOrganization);
        return originalOrganization;
    }

    /**
     * 设置字段默认值
     * @param organizationDto
     * @param propertyName
     */
    public void setDefaultValues(OrganizationDto organizationDto, String propertyName) {
        switch (propertyName) {
            case "category":
                organizationDto.setCategory("其他");
                break;
            case "uscc":
                organizationDto.setUscc(null);
                break;
            case "representative":
                organizationDto.setRepresentative(null);
                break;
            case "description":
                organizationDto.setDescription(null);
                break;
            case "country":
                organizationDto.setCountry("CHN");
                break;
            case "divisionCode":
                organizationDto.setDivisionCode("00000000");
                break;
            case "address":
                organizationDto.setAddress(null);
                break;
            case "postCode":
                organizationDto.setPostCode(null);
                break;
            case "status":
                organizationDto.setStatus(1); // Default Integer value
                break;
            case "approver":
                organizationDto.setApprover(null);
                break;
            case "approvalTime":
                organizationDto.setApprovalTime(null); // Default Date value
                break;
            default:
                // Handle the case when propertyName doesn't match any of the expected values.
                break;
        }
    }

    /**
     * @description:核验-标准化方法 TODO: 待优化，添加注解机制
     * 核验方法必须返回一个boolean值，true表示通过核验，false表示未通过核验
     * 核验方法必须接收一个参数，该参数类型为待核验的字段值
     * 核验方法必须使用@Verify注解进行标识
     * 核验方法必须使用@Standardize注解进行标识
     * 核验方法必须使用@Standardize注解的value属性指定标准化的方法
     */
    private class KeyVerifyStandardizeTableItem {
        String key;
        Method verify;
        Method standatdize;

        public KeyVerifyStandardizeTableItem(String key, Method verify, Method standatdize) {
            this.key = key;
            this.verify = verify;
            this.standatdize = standatdize;
        }
    }

    /**
     * @description:获取目标字段的值
     * @param organizationDto
     * @param attributeName
     * @return
     */
    public static Object getAttributeValue(OrganizationDto organizationDto, String attributeName) {
        try {
            Class<?> clazz = organizationDto.getClass();
            Field field = clazz.getDeclaredField(attributeName);
            field.setAccessible(true);
            return field.get(organizationDto);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * @description:设置目标字段的值
     * @param organizationDto
     * @param attributeName
     * @param value
     */
    public static void setAttributeValue(OrganizationDto organizationDto, String attributeName, Object value) {
        try {
            Class<?> clazz = organizationDto.getClass();
            Field field = clazz.getDeclaredField(attributeName);
            field.setAccessible(true);
            field.set(organizationDto, value);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 逻辑删除
     * 假删除，将数据状态设置为2
     * @Param id
     */
    @Override
    public boolean logicalDelete(String id) {
        OrganizationDto organization = organizationMapper.selectOrganizationById(id);
        organization.setStatus(2);
        organization.setApprover("DEFAULT");
        organization.setApprovalTime(new Date());
        organizationMapper.updateOrganization(organization);
        return true;
    }

    /**
     * @description:物理删除
     * 物理删除，将数据从数据库中删除
     */
    @Override
    public boolean physicalDelete(String id) throws InvocationTargetException, IllegalAccessException {

        List<String> errorList = new ArrayList<>(); // 记录错误信息
        // 获取所有依赖Father的表
        OrganizationDto organizationDto = organizationMapper.selectOrganizationById(id);
        int count = 0;

        for (ForeignDataItem item : foreignManageUtils.getForeignDataItem(Organization.class.getName())) {
            List list = (List) item.searchByForeignKeyMethod.invoke(
                    applicationContext.getBean((Class) item.serviceClass),
                    BeanUtil.getFieldValue(organizationDto, item.foreignKey)
            );
            errorList.addAll(list);
            count += list.size();
        }

        if (count > 0) {
            log.error("物理删除机构" + id + "失败，存在依赖：" + errorList);
            throw new BizException(CommonEnum.DELETE_FALSE);
        }

        organizationMapper.physicalDelete(id);
        return true;
    }


    /**
     * @descritpion：合并机构
     * 合并机构时，需要将依赖待删除机构下的所有数据转移到保留机构下
     * **/
    @Override
    public OrganizationDto merge(OrganizationDto organizationDto, OrganizationDto deletedOrganization) throws InvocationTargetException, IllegalAccessException {

        // 获取所有依赖组织表的外键关系
        for (ForeignDataItem item : foreignManageUtils.getForeignDataItem(Organization.class.getName())) {
            // 首先查询是否任然有依赖即将被删除数据的记录
            List list = (List) item.searchByForeignKeyMethod.invoke(
                    applicationContext.getBean((Class) item.serviceClass),
                    BeanUtil.getFieldValue(deletedOrganization, item.foreignKey)
            );
            // 如果有，执行合并操作
            if (list != null && list.size() > 0) {
                log.info("在合并机构" + deletedOrganization + "时，发现了依赖项" + list);
                item.mergeByForeignKeyMethod.invoke(
                        applicationContext.getBean((Class) item.serviceClass),
                        BeanUtil.getFieldValue(organizationDto, item.foreignKey),
                        BeanUtil.getFieldValue(deletedOrganization, item.foreignKey)
                );
            }
        }

        // 依赖清理结束后，删除数据
        organizationMapper.physicalDelete(deletedOrganization.getOrganizationId());
        return organizationDto;
    }
}
